package crawler;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * This program uses patterns to parse dates and names from a Wikipedia html
 * page to create trivia questions. So far, this program makes four basic questions:
 * 
 * 1. If the subject of the page is a person, it creates a question based on their birth year.
 * 2. If the subject is a company, it creates a question based on the year it was founded.
 * 3. If the subject is an operating system, it creates a question based on the year it was released.
 * 4. If the subject is a programming language, it creates a question based on the year it initially appeared in.
 * 
 * @author James Jensen
 * @version February 11, 2012
 */

public class QuestionGenerator {

	private List<String> tableContent = new CopyOnWriteArrayList<String>(); // list of table content from a Wikipedia page
	private List<String> pageContent = new CopyOnWriteArrayList<String>(); // list of sentences from a Wikipedia page
	private String title = "";	// title of the page which is the subject of the questions
	private String pageUrl = ""; // url of the source page
	private PageQnA pageQnAs; // question and answers
	final private Pattern DATE_PATTERN = Pattern.compile("\\d{4}"); // pattern to recognize a date
    final private Pattern ANY_NUMBER = Pattern.compile("\\d+");	// pattern to match a number
	final private String CONTAINS_DIGIT = ".*?[\\d]+.*?";
	
	/*
	 * Identifies what the subject is so the generator can properly replace pronouns with the subject
	 * 0 = Person
	 * 1 = Company
	 * 2 = Operating System
	 * 3 = Programming Language
	 */
	private int subject;
	
	// default constructor
	public QuestionGenerator() {
	}
	
	/**
	 * Constructor takes an List<String>. Each element is a sentence from the
	 * Wikipedia page.
	 * 
	 * @param sentenceList 
	 */
	public QuestionGenerator(String url, String pageTitle, List<String> tableList, List<String> sentenceList) {
		pageUrl = url; 
		title = pageTitle;
		tableContent =  tableList;
		pageContent =  sentenceList;
		pageQnAs = new PageQnA(pageUrl, title);
		
		makeQuestions();
	}
	
	public PageQnA getPageQnA() {
		return pageQnAs;
	}
	
	private void makeQuestions() {
		tableQuestions();
		pageQuestions();
	}
	
	/**
	 * Creates questions from the main table
	 */
	private void tableQuestions() {
		Matcher dataMatcher;

		/* Extract just subject of the page */
		title = title.replaceAll(" \\(.*\\)", "");	// remove parenthesis

		// cycle through the tableContent to find questions
		for(int i = 0; i < tableContent.size(); i++) {
			String current = tableContent.get(i); // get the current page

			// if the page is about a person, create a question about the year they were born
			if( current.contains("Born") ) {
				int birthYear; // year subject was born
				subject = 0;
				
				do {
					i++; // skip a line and go to the next one;
					current = tableContent.get(i); // get that line
				} while( !current.matches(CONTAINS_DIGIT) );
				
				current = tableContent.get(i); // get that line
				dataMatcher = DATE_PATTERN.matcher(current); // matches the series of 4 digits
				dataMatcher.find();	// finds the next 4 digit number 
				birthYear = Integer.parseInt( dataMatcher.group(0) ); // gets the year and parses it into an int 
				
				birthDateQ(birthYear); // create a birth date question
				break;
			}

			// if the page is about a company, create a question about what year it was founded
			else if( current.contains("Founded") ) {
				int foundedYear;
				subject = 1;
				
				do {
					i++; // skip a line and go to the next one;
					current = tableContent.get(i); // get that line
				} while( !current.matches(CONTAINS_DIGIT) );
					
				dataMatcher = DATE_PATTERN.matcher(current);
				dataMatcher.find();
				foundedYear = Integer.parseInt( dataMatcher.group(0) );

				foundedDateQ(foundedYear); // create a founded date question
				break;
			}

			// if the page is about an OS
			else if( current.contains("Initial release") ) {
				int releaseYear;
				subject = 2;
				
				do {
					i++; // skip a line and go to the next one;
					current = tableContent.get(i); // get that line
				} while( !current.matches(CONTAINS_DIGIT) );

				dataMatcher = DATE_PATTERN.matcher(current);
				dataMatcher.find();
				releaseYear = Integer.parseInt( dataMatcher.group(0) );
				
				osReleaseQ(releaseYear); // create a founded date question
				break;
			}
			
			// if the page is about a programming/scripting language
			else if( current.contains("Appeared in") ) {
				int appearedYear;
				subject = 3;
				
				do {
					i++; // skip a line and go to the next one;
					current = tableContent.get(i); // get that line
				} while( !current.matches(CONTAINS_DIGIT) );
				
				dataMatcher = DATE_PATTERN.matcher(current);
				dataMatcher.find();
				appearedYear = Integer.parseInt( dataMatcher.group(0) );
				
				langFirstQ(appearedYear); // create a founded date question
				break;
			}
		}
	}
	
	/**
	 * Creates questions from the list of sentences extracted from the source page
	 */
	private void pageQuestions() {
		Matcher dataMatcher;	// to match the pattern
	    
		// loop through the list of sentences
		for(int i = 0; i < pageContent.size(); i++) {
			String current = pageContent.get(i); // get the current sentence
			String question;
			int answer;
			
			dataMatcher = ANY_NUMBER.matcher(current); // match a number
			dataMatcher.find();	// find all matches
			answer = Integer.parseInt( dataMatcher.group(0) ); // get the first number
			question = current.replaceFirst("" + answer, "_____");	// replace the number with underscores
			question = question.replaceAll("&amp;", "&");
			
			/******  Replace pronouns with proper nouns ******/
			if(subject == 0) {
				question = question.replaceAll(" he ", " " + title + " ");
				question = question.replaceAll(" she ", " " + title + " ");
				question = question.replaceAll(" him ", " " + title + " ");
				question = question.replaceAll("He ", title + " ");
				question = question.replaceAll("She ", title + " ");
				question = question.replaceAll(" his ", " " + title + "\'s ");
				question = question.replaceAll(" her ", " " + title + "\'s ");
				question = question.replaceAll("His ", title + "\'s ");
				question = question.replaceAll("Her ", title + "\'s ");
			}
			else {
				question = question.replaceAll(" it ", " " + title + " ");
				question = question.replaceAll("It ", title + " ");
				question = question.replaceAll(" its ", " " + title + "\'s ");
				question = question.replaceAll("Its ", title + "\'s ");
			}
			
			pageQnAs.addQnA(question, answer);	// add the question and answer
		}
		
	}
	
	/**
	 * Creates a question about the birth year of a person
	 * @param answer	The numerical year
	 */
	private void birthDateQ(int answer) {
		String question = "What year was " + title + " born?";
		pageQnAs.addQnA(question, answer);
	}
	
	/**
	 * Creates a question about the date a company was founded
	 * @param answer	The numerical year
	 */
	private void foundedDateQ(int answer) {
		String question = "What year was " + title + " founded?";
		pageQnAs.addQnA(question, answer);
	}
	
	/**
	 * Creates a question about the date an OS was initially released
	 * @param answer	The numerical year
	 */
	private void osReleaseQ(int answer) {
		String question = "What year was the " + title + " operating system released?";
		pageQnAs.addQnA(question, answer);
	}
	
	/**
	 * Creates a question about when a programming/scripting language was first appeared
	 * @param desc	The String description of the language
	 * @param answer	The numerical year
	 */
	private void langFirstQ(int answer) {
		String question = "The " + title + " programming language first appeared in what year?";
		pageQnAs.addQnA(question, answer);
	}

}
